from fastapi import APIRouter, HTTPException, Depends
from pydantic import BaseModel
from abc import ABC, abstractmethod
from typing import List, Dict, Optional, Type
import uuid  # 用于生成唯一订单ID


router = APIRouter(prefix="/orders", tags=["代驾订单"])

# 订单状态枚举（规范状态流转）
VALID_STATUSES = ["pending", "accepted", "in_service", "completed", "cancelled"]

class Observer(ABC):
    """观察者接口：所有观察者必须实现update方法"""
    @abstractmethod
    async def update(self, order_id: str, old_status: str, new_status: str, **kwargs):
        """
        处理订单状态变更
        :param order_id: 订单ID
        :param old_status: 旧状态
        :param new_status: 新状态
        :param kwargs: 额外参数（如司机ID、用户ID等）
        """
        pass

class UserNotificationObserver(Observer):
    """观察者1：通知用户订单状态变更"""
    async def update(self, order_id: str, old_status: str, new_status: str,** kwargs):
        # 从kwargs中获取用户ID
        user_id = kwargs.get("user_id")
        # 构造通知消息
        message = f"【安途代驾】用户{user_id}的订单{order_id}状态更新：{old_status}→{new_status}"
        # 实际项目中调用短信/APP推送API（此处模拟）
        print(f"[用户通知] {message}")

class DriverNotificationObserver(Observer):
    """观察者2：通知司机订单状态变更"""
    async def update(self, order_id: str, old_status: str, new_status: str, **kwargs):
        # 从kwargs中获取司机ID
        driver_id = kwargs.get("driver_id")
        # 如果没有司机ID则不处理
        if not driver_id:
            return
        # 根据不同状态构造不同的通知消息
        if new_status == "accepted":
            message = f"司机{driver_id}，您已成功接单（订单{order_id}），请尽快前往接驾"
        elif new_status == "completed":
            message = f"司机{driver_id}，订单{order_id}已完成，请确认服务"
        else:
            message = f"司机{driver_id}，订单{order_id}状态更新为{new_status}"
        print(f"[司机通知] {message}")

class PaymentObserver(Observer):
    """观察者3：订单完成时触发支付"""
    async def update(self, order_id: str, old_status: str, new_status: str,** kwargs):
        # 当订单状态变为已完成时触发支付流程
        if new_status == "completed":
            # 获取用户ID
            user_id = kwargs.get("user_id")
            # 模拟支付单生成
            print(f"[支付系统] 为用户{user_id}的订单{order_id}生成支付单，金额计算中...")

class OrderLogObserver(Observer):
    """观察者4：记录订单状态变更日志"""
    async def update(self, order_id: str, old_status: str, new_status: str, **kwargs):
        # 记录订单状态变更日志（实际项目中写入数据库或日志系统）
        print(f"[系统日志] 订单{order_id}状态变更：{old_status}→{new_status}（时间：系统当前时间）")





class OrderSubject:
    """订单主题：被观察的对象，管理状态和观察者"""#作为被观察对象，管理订单状态和观察者，状态变更时自动通知所有注册的观察者。
    def __init__(self, order_id: str, user_id: str):
        self.order_id = order_id  # 订单唯一ID
        self.user_id = user_id    # 下单用户ID
        self.driver_id: Optional[str] = None  # 接单司机ID（初始为空）
        self._status: str = "pending"  # 初始状态：待接单
        self.observers: List[Observer] = []  # 观察者列表

    @property
    def status(self) -> str:
        return self._status

    async def set_status(self, new_status: str,** kwargs):
        """
        更新订单状态并通知观察者
        :param new_status: 新状态
        :param kwargs: 额外参数（如司机ID）
        """
        # 校验状态合法性
        if new_status not in VALID_STATUSES:
            raise ValueError(f"无效状态：{new_status}，合法状态：{VALID_STATUSES}")
        # 状态未变更则不处理
        if self._status == new_status:
            return
        # 记录旧状态，更新新状态
        old_status = self._status
        self._status = new_status
        # 接单时必须传入司机ID
        if new_status == "accepted":
            self.driver_id = kwargs.get("driver_id")
            if not self.driver_id:
                raise ValueError("接单状态必须指定司机ID")
        # 通知所有观察者（异步执行）
        for observer in self.observers:
            await observer.update(
                order_id=self.order_id,
                old_status=old_status,
                new_status=new_status,
                user_id=self.user_id,
                driver_id=self.driver_id
            )

    def add_observer(self, observer: Observer):
        """添加观察者"""
        if observer not in self.observers:
            self.observers.append(observer)

    def remove_observer(self, observer: Observer):
        """移除观察者"""
        if observer in self.observers:
            self.observers.remove(observer)



# class OrderSubject:
#     """订单主题：被观察的对象，管理状态和观察者"""
#     def __init__(self, order_id: str, user_id: str):
#         self.order_id = order_id  # 订单唯一ID
#         self.user_id = user_id    # 下单用户ID
#         self.driver_id: Optional[str] = None  # 接单司机ID（初始为空）
#         self._status: str = "pending"  # 初始状态：待接单
#         self.observers: List[Observer] = []  # 观察者列表
#
#     @property
#     def status(self) -> str:
#         return self._status
#
#     async def set_status(self, new_status: str,** kwargs):
#         """
#         更新订单状态并通知观察者
#         :param new_status: 新状态
#         :param kwargs: 额外参数（如司机ID）
#         """
#         # 校验状态合法性
#         if new_status not in VALID_STATUSES:
#             raise ValueError(f"无效状态：{new_status}，合法状态：{VALID_STATUSES}")
#         # 状态未变更则不处理
#         if self._status == new_status:
#             return
#         # 记录旧状态，更新新状态
#         old_status = self._status
#         self._status = new_status
#         # 接单时必须传入司机ID
#         if new_status == "accepted":
#             self.driver_id = kwargs.get("driver_id")
#             if not self.driver_id:
#                 raise ValueError("接单状态必须指定司机ID")
#         # 通知所有观察者（异步执行）
#         for observer in self.observers:
#             await observer.update(
#                 order_id=self.order_id,
#                 old_status=old_status,
#                 new_status=new_status,
#                 user_id=self.user_id,
#                 driver_id=self.driver_id
#             )
#
#     def add_observer(self, observer: Observer):
#         """添加观察者"""
#         if observer not in self.observers:
#             self.observers.append(observer)
#
#     def remove_observer(self, observer: Observer):
#         """移除观察者"""
#         if observer in self.observers:
#             self.observers.remove(observer)


# 内存存储订单（key: order_id, value: OrderSubject）
order_store: Dict[str, OrderSubject] = {}

# Pydantic模型：创建订单请求
class CreateOrderRequest(BaseModel):
    user_id: str  # 用户ID

# Pydantic模型：更新订单状态请求
class UpdateStatusRequest(BaseModel):
    new_status: str
    driver_id: Optional[str] = None  # 接单时必填

# 依赖：获取订单（用于接口复用）
async def get_order(order_id: str) -> OrderSubject:
    if order_id not in order_store:
        raise HTTPException(status_code=404, detail="订单不存在")
    return order_store[order_id]

@router.post("/", summary="创建代驾订单")
async def create_order(req: CreateOrderRequest):
    # 生成唯一订单ID（UUID）
    order_id = f"AT-{uuid.uuid4().hex[:8].upper()}"
    # 创建订单主题
    order = OrderSubject(order_id=order_id, user_id=req.user_id)
    # 注册观察者（根据业务需求动态添加）
    order.add_observer(UserNotificationObserver())
    order.add_observer(DriverNotificationObserver())
    order.add_observer(PaymentObserver())
    order.add_observer(OrderLogObserver())
    # 存入内存（实际项目用数据库）
    order_store[order_id] = order
    return {
        "code": 0,
        "message": "订单创建成功",
        "data": {
            "order_id": order_id,
            "status": order.status,
            "user_id": req.user_id
        }
    }

@router.put("/{order_id}/status", summary="更新订单状态")
async def update_order_status(
    req: UpdateStatusRequest,  # 无默认值参数在前
    order: OrderSubject = Depends(get_order)  # 有默认值参数在后
):

    try:
        # 调用订单的set_status方法（自动通知观察者）
        await order.set_status(new_status=req.new_status, driver_id=req.driver_id)
        return {
            "code": 0,
            "message": "状态更新成功",
            "data": {
                "order_id": order.order_id,
                "old_status": order.status,  # 实际为新状态（已更新）
                "new_status": req.new_status,
                "driver_id": order.driver_id
            }
        }
    except ValueError as e:
        raise HTTPException(status_code=400, detail=str(e))

@router.get("/{order_id}", summary="查询订单详情")
async def get_order_detail(order: OrderSubject = Depends(get_order)):
    return {
        "code": 0,
        "data": {
            "order_id": order.order_id,
            "user_id": order.user_id,
            "driver_id": order.driver_id,
            "status": order.status
        }
    }